# -*- coding: utf-8 -*-
import asyncio
from bleak import BleakClient, BleakScanner
from bleak.backends.characteristic import BleakGATTCharacteristic
from bleak import BleakScanner
import queue
from tkinter import messagebox

bleConnStaQue = queue.Queue(maxsize=1)
disConnQue = queue.Queue(maxsize=1)
cmdQue = queue.Queue(maxsize=1)
setSNQue = queue.Queue(maxsize=1)
bleRxDataQue = queue.Queue(maxsize=1)

#设备的Characteristic UUID
par_notification_characteristic = "0000ffe1-0000-1000-8000-00805f9b34fb"
#设备的Characteristic UUID（具备写属性Write）
par_write_characteristic = "0000ffe1-0000-1000-8000-00805f9b34fb"

#设备的NAME
par_device_name = "Lightbox"
# par_device_name = "MC-"
#设备的MAC地址
par_device_addr = "00:00:00:00:00:00"

BLE_DISCONNECT = 0
BLE_CONNECT_OK = 1
BLE_CONNECT_FAIL = 2
BLE_NOT_FIND  = 3


CHECK_RED_CMD = 0
CHECK_GREEN_CMD = 1
CHECK_BLUE_CMD = 2
CHECK_WHITE_CMD = 3
CHECK_CLOSE_ALL_CMD = 4
CHECK_OFF_CMD = 5
GET_SN_CMD = 6
BIND_SN_CMD = 7
EXIT_THREAD_CMD = 8
GET_RANDOM_CMD = 9

redLight = bytearray([0xAA, 0x09, 0x03, 0xFF, 0x00, 0x00, 0x01, 0x23, 0x45, 0x67, 0xAC, 0xF6])
greenLight = bytearray([0xAA, 0x09, 0x03, 0x00, 0xFF, 0x00, 0x01, 0x23, 0x45, 0x67, 0xB7, 0xF6])
blueLitht = bytearray([0xAA, 0x09, 0x03, 0x00, 0x00, 0xFF, 0x01, 0x23, 0x45, 0x67, 0xB7, 0xED])
closeAll = bytearray([0xAA, 0x09, 0x03, 0x00, 0x00, 0x00, 0x01, 0x23, 0x45, 0x67, 0xA3, 0xF9])
LEDOn = bytearray([0xAA, 0x07, 0x02, 0x01, 0x01, 0x23, 0x45, 0x67, 0xD2, 0xAE])
LEDOff = bytearray([0xAA, 0x07, 0x02, 0x02, 0x01, 0x23, 0x45, 0x67, 0x96, 0xAE])
bindSN = bytearray([0xAA, 0x08, 0x31, 0x4C, 0x42, 0x30, 0x30, 0x30, 0x31, 0xCD, 0xB6])
getSN = bytearray([0xAA, 0x06, 0x22, 0x01, 0x23, 0x45, 0x67, 0x7B, 0x36])
getRandom = bytearray([0xAA, 0x06, 0x23, 0x01, 0x23, 0x45, 0x67, 0x46, 0xf6])

#准备发送的消息 AA 09 03 FF0000 01234567 ACF6
# bleSendStr = bytearray([0xAA,0x09,0x03,0xFF,0x00,0x00,0x01,0x23,0x45,0x67,0xac,0xf6])

def activeBlueth():
    print("开始连接蓝牙设备...")
    asyncio.run(connectBluetooth())

#监听回调函数，此处为打印消息
def notification_handler(characteristic: BleakGATTCharacteristic, data):
    global bleRxDataQue

    # print("rev data:", str(data))
    num = bytes.fromhex(data.hex()) # 将接收到的数据转换成数组
    # print("num=",num)
    bleRxDataQue.put(num)
    # print("num len:",len(num))
    # for i in range(0,len(num)) :
    #     print("num[{}]:".format(i),num[i])

def handleButtonCmd(cmd):
    if cmd == CHECK_RED_CMD:
        bleSendStr = redLight
    elif cmd == CHECK_GREEN_CMD:
        bleSendStr = greenLight
    elif cmd == CHECK_BLUE_CMD:
        bleSendStr = blueLitht
    elif cmd == CHECK_WHITE_CMD:
        bleSendStr = LEDOn
    elif cmd == CHECK_CLOSE_ALL_CMD:
        bleSendStr = closeAll
    elif cmd == CHECK_OFF_CMD:
        bleSendStr = LEDOff
    elif cmd == GET_SN_CMD:
        bleSendStr = getSN
    elif cmd == GET_RANDOM_CMD:
        bleSendStr = getRandom
    elif cmd == BIND_SN_CMD:
        # bleSendStr = bindSN
        bleSendStr = setSNQue.get()

    
    return bleSendStr

async def connectBluetooth():
    global bleConnStaQue
    bleFind = 0

    print("开始扫描周围的蓝牙设备...")
    devices = await BleakScanner.discover()
    for d in devices:   #d为类，其属性有：d.name为设备名称，d.address为设备地址
        # print("add:{},name:".format(d.address),d.name)
        # print("bluetooth:", d.name)
        # print('len=',len(d.name))
        if par_device_name == str(d.name):
            print("find target bluetooth:", d.name)
            print('len=',len(d.name))
            global par_device_addr
            par_device_addr = d.address
            bleFind = 1
            break

    if bleFind == 0:
        global bleConnStaQue
        # print("not find target bluetooth")
        messagebox.showwarning('提示', '没有找到可用的蓝牙设备')
        bleConnStaQue.put(BLE_NOT_FIND)
        return

    #基于MAC地址查找设备
    device = await BleakScanner.find_device_by_address(
        par_device_addr, cb = dict(use_bdaddr = False)  #use_bdaddr判断是否是MOC系统
    )
    if device is None:
        # print("could not find device with address '%s'", par_device_addr)
        messagebox.showwarning('提示', '没有找到可用的蓝牙设备')

        bleConnStaQue.put(BLE_NOT_FIND)
        return

    #事件定义
    disconnected_event = asyncio.Event()

    #断开连接事件回调
    def disconnected_callback(client):
        print("Disconnected callback called!")
        disconnected_event.set()
        bleConnStaQue.put(BLE_DISCONNECT)
        return

    # print("connecting to bluetooth...")
    async with BleakClient(device, disconnected_callback = disconnected_callback) as client:
        # print("Connected bluetooth success")
        messagebox.showwarning('提示', '蓝牙设备已连接')

        bleConnStaQue.put(BLE_CONNECT_OK)

        await client.start_notify(par_notification_characteristic, notification_handler)
        global cmdQue

        while True:
            if not cmdQue.empty():
                
                cmd = cmdQue.get()
                if cmd == EXIT_THREAD_CMD:
                    # await disconnected_event.wait()       #休眠直到设备断开连接，有延迟。此处为监听设备直到断开为止
                    await client.stop_notify(par_notification_characteristic)
                    await client.disconnect()
                    await asyncio.sleep(2)           #休眠0.1秒
                    print('结束线程')
                    messagebox.showwarning('提示', '本次检测结束')
                    disConnQue.put(1)

                    break
                else:
                    sendData = handleButtonCmd(cmd)
                    await client.write_gatt_char(par_write_characteristic, sendData)
            else:
                await asyncio.sleep(0.1)           #休眠0.1秒
        # await asyncio.sleep(10.0)           #程序监听的时间，此处为10秒


if __name__ == "__main__":
    asyncio.run(connectBluetooth())
